package br.com.ss.util;

import java.text.ParseException;
import java.util.Date;
import java.util.GregorianCalendar;

/**
 * Classe utilitzada para manipulacao de datas.
 * 
 *@author Rodrigo Carvalho 
 */
public class DateUtil {

	/**
	 * Metodo responsavel por converder um Date em um GregorianCalendar
	 * @param Date data
	 * @return GregorianCalendar 
	 * @author Rodrigo Carvalho
	 * 
	 */
	private static GregorianCalendar convertDate(Date data){
		
		if(data != null){
			GregorianCalendar calendar = new GregorianCalendar();  
			calendar.setTime(data);
			return calendar;
		}
		
		return null;
	}

	
	/**
	 * Metodo responsavel por remover Horas, minutos e segundos da Hora
	 * @param Date data
	 * @return GregorianCalendar 
	 * @author Rodrigo Carvalho
	 * 
	 */
	private static GregorianCalendar zerarHoraDate(Date data){
		
		if(data != null){
			GregorianCalendar calendar = new GregorianCalendar();  
			calendar.setTime(data);
			calendar.set(GregorianCalendar.HOUR_OF_DAY, 0);
			calendar.set(GregorianCalendar.MINUTE, 0);
			calendar.set(GregorianCalendar.SECOND, 0);
			calendar.set(GregorianCalendar.MILLISECOND, 0);
			
			return calendar;
		}
		
		return null;
	}

	
	/**
	 * Metodo responsavel por retornar o dia de um Date
	 * @param Date data
	 * @return int 
	 * @author Rodrigo Carvalho
	 * 
	 */
	public static int diaDate(Date data){
		
		if(data != null){
			GregorianCalendar calendar = convertDate(data);
			return calendar.get(GregorianCalendar.DAY_OF_MONTH);
		}
		
		return 0;
	}

	/**
	 * Metodo responsavel por retornar o mes de um Date
	 * @param Date data
	 * @return int 
	 * @author Rodrigo Carvalho
	 * 
	 */
	public static int mesDate(Date data){
		
		if(data != null){
			GregorianCalendar calendar = convertDate(data);
			return calendar.get(GregorianCalendar.MONTH);
		}
		
		return 0;
	}

	
	/**
	 * Metodo responsavel por retornar o ano de um Date
	 * @param Date data
	 * @return int 
	 * @author Rodrigo Carvalho
	 * 
	 */
	public static int anoDate(Date data){
		
		if(data != null){
			GregorianCalendar calendar = convertDate(data);
			return calendar.get(GregorianCalendar.YEAR);
		}
		
		return 0;
	}

	
	/**
	 * Metodo responsavel por retornar as hora de um Date
	 * @param Date data
	 * @return int 
	 * @author Rodrigo Carvalho
	 * 
	 */
	public static int hourDate(Date data){
		
		if(data != null){
			GregorianCalendar calendar = convertDate(data);
			return calendar.get(GregorianCalendar.HOUR_OF_DAY);
		}
		
		return 0;
	}
	
	/**
	 * Metodo responsavel por retornar os minutos de um Date
	 * @param Date data
	 * @return int 
	 * @author Rodrigo Carvalho
	 * 
	 */
	public static int minuteDate(Date data){
		
		if(data != null){
			GregorianCalendar calendar = convertDate(data);
			return calendar.get(GregorianCalendar.MINUTE);
		}
		
		return 0;
	}
	
	/**
	 * Metodo responsavel por retornar os segundos de um Date
	 * @param Date data
	 * @return int 
	 * @author Rodrigo Carvalho
	 * 
	 */
	public static int secondDate(Date data){
		
		if(data != null){
			GregorianCalendar calendar = convertDate(data);
			return calendar.get(GregorianCalendar.SECOND);
		}
		
		return 0;
	}
	
	
	/**
	 * Metodo para comparar a igualdade entre duas datas, compara 
	 * somente a data despresando hora, minuto e segundos.
	 * 
	 * @param Date data1
	 * @param Date data2
	 * @return Retorna True caso as datas sejam iguais e false caso contrario
	 * @author Rodrigo Carvalho
	 * 
	 */
	public static boolean compareDateWithoutHours(Date data1, Date data2) {
		
		if((data1 == null && data2 != null) || (data1 != null && data2 == null)){
			return false;
		} else if(data1 == null && data2 == null){
			return true;
		}
		
		String s1 =  "" + diaDate(data1) + mesDate(data1) + anoDate(data1);
		String s2 =  "" + diaDate(data2) + mesDate(data2) + anoDate(data2);
		return s1.equals(s2);
	}

	/**
	 * Metodo para comparar a igualdade entre duas datas. 
	 * 
	 * @param Date data1
	 * @param Date data2
	 * @return Retorna True caso as datas sejam iguais e false caso contrario
	 * @author Rodrigo Carvalho
	 * 
	 */
	public static boolean compareDate(Date data1, Date data2) {
		
		if((data1 == null && data2 != null) || (data1 != null && data2 == null)){
			return false;
		} else if(data1 == null && data2 == null){
			return true;
		}
		
		String s1 =  "" + diaDate(data1) + mesDate(data1) + anoDate(data1);
		String s2 =  "" + diaDate(data2) + mesDate(data2) + anoDate(data2);
		return s1.equals(s2);
	}
	
	/**
	 *  Metodo para testar se uma data e anterior a outra
	 * @param Date data1
	 * @param Date data2
	 * @return boolean
	 * @author Rodrigo Carvalho
	 */
	public static boolean beforeDate(Date data1, Date data2) {
		if(data1 == null || data2 == null)
			return false;
		return data1.before(data2);
	}
	
	/**
	 *  Metodo para testar se uma data e depois a outra 
	 * 
	 * @param Date data1
	 * @param Date data2
	 * @return boolean
	 * @author Rodrigo Carvalho
	 */
	public static boolean afterDate(Date data1, Date data2) throws ParseException {
		if(data1 == null || data2 == null)
			return false;
		return data1.after(data2);
	}
	
	/**
	 *  Metodo para testar se uma data e anterior a outra 
	 *  despresando a hora, minuto e segundos.
	 * @param Date data1
	 * @param Date data2
	 * @return boolean
	 * @author Rodrigo Carvalho
	 */
	public static boolean beforeDateWithoutHours(Date data1, Date data2) {
		if(data1 == null || data2 == null)
			return false;
		return zerarHoraDate(data1).before(zerarHoraDate(data2));
	}
	
	/**
	 *  Metodo para testar se uma data e depois a outra 
	 * despresando a hora, minuto e segundos.
	 * 
	 * @param Date data1
	 * @param Date data2
	 * @return boolean
	 * @author Rodrigo Carvalho
	 */
	public static boolean afterDateWithoutHours(Date data1, Date data2) throws ParseException {
		if(data1 == null || data2 == null)
			return false;
		return zerarHoraDate(data1).after(zerarHoraDate(data2));
	}
	
	/**
	 * Retorna a soma dos dias
	 * @param Date date
	 * @param int days
	 * @return Date
	 * @author Rodrigo Carvalho
	 */
	public static Date sumDays(Date date, int days) {
		
		long secondInMillis = 1000; 
		long minuteInMillis = secondInMillis * 60; 
		long hourInMillis = minuteInMillis * 60; 
		long dayInMillis = hourInMillis * 24; 
//		long yearInMillis = dayInMillis * 365;
		
		long data = date.getTime();  
		long dias = days * dayInMillis;
		long soma = data + dias;
		
		return new Date(soma);
	}


	/**
	 * Metodo responsavel por remover a quantidade de dias informada
	 * @param Date date
	 * @param int days
	 * @return Date
	 * @author Rodrigo Carvalho
	 * 
	 */
	public static Date subtractDays(Date date, int days) {
		
		long secondInMillis = 1000; 
		long minuteInMillis = secondInMillis * 60; 
		long hourInMillis = minuteInMillis * 60; 
		long dayInMillis = hourInMillis * 24; 
//		long yearInMillis = dayInMillis * 365;
		
		long data = date.getTime();  
		long dias = days * dayInMillis;
		long subtracao = data - dias;
		
		return new Date(subtracao);
	}
	
	
	/**
	 * Retorna a diferenca emtre duas datas
	 * @param dataMaior
	 * @param dataMenor
	 * @return retorna o a diferenca em numero de dias
	 * @author Rodrigo Carvalho
	 */
	public static Long diferencaDates(Date dataMaior, Date dataMenor) {
		
		long diff = dataMaior.getTime() - dataMenor.getTime(); 
		long secondInMillis = 1000; 
		long minuteInMillis = secondInMillis * 60; 
		long hourInMillis = minuteInMillis * 60; 
		long dayInMillis = hourInMillis * 24; 
		long yearInMillis = dayInMillis * 365; 
		
		long elapsedYears = diff / yearInMillis; 
		diff = diff % yearInMillis; 
		long elapsedDays = diff / dayInMillis; 
		diff = diff % dayInMillis; 
		
		return elapsedDays + (elapsedYears * 365);
	}
	
	/**
	 * Retorna a diferenca emtre duas datas
	 * @param Date dataMaior
	 * @param Date dataMenor
	 * @return retorna o a diferenca em horas
	 */
	public static Long differenceDatesInHours(Date dataMaior, Date dataMenor) {
		
		long diff = dataMaior.getTime() - dataMenor.getTime(); 
		long secondInMillis = 1000; 
		long minuteInMillis = secondInMillis * 60; 
		long hourInMillis = minuteInMillis * 60; 
		long dayInMillis = hourInMillis * 24; 
		long yearInMillis = dayInMillis * 365;
		
		long elapsedYears = diff / yearInMillis; 
		diff = diff % yearInMillis; 
		long elapsedDays = diff / dayInMillis; 
		diff = diff % dayInMillis;
		long elapsedHours = diff / hourInMillis; 
		diff = diff % hourInMillis;
		
		return elapsedHours + ((elapsedDays + (elapsedYears * 365)) * 24);
	
	}
	
	/**
	 * Retorna um Date sem as informacoes de hora, minuto e segundo
	 * @param Date data
	 * @return Retorna um Date sem os minutos, segundos ou horas.
	 * @author Rodrigo Carvalho
	 * 
	 */
	public static Date onlyDate(Date data) {
			GregorianCalendar dataZerada = zerarHoraDate(data);
		  return dataZerada.getTime();
	}
	
	
}
